package com.kb.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpStatus;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.module.system.api.category.CategoryApi;
import cn.iocoder.yudao.module.system.api.category.dto.CategoryRespDTO;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.kb.common.MeException;
import com.kb.domain.ComponentInfo;
import com.kb.dto.ComponentSyncDTO;
import com.kb.entity.*;
import com.kb.mapper.mysql.*;
import com.kb.service.ComponentDataService;
import com.kb.service.impl.gc.ComponentEsServiceImpl;
import com.kb.util.GCutil;
import com.xxl.job.core.context.XxlJobHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@DS("master")
@Service
@Slf4j
public class ComponentDataServiceImpl extends ServiceImpl<ComponentDao, ComponentData> implements ComponentDataService {

    @Resource
    private ComponentDao componentDao;
    @Resource
    private ComponentDataHeaderFieldDao componentDataHeaderFieldDao;
    @Resource
    private CallbackNotificationServiceImpl callbackNotificationService;
    @Resource
    private CallbackNotificationDao callbackNotificationDao;

    @Value("${gc.gcUrl}")
    private String gcUrl;

    @Value("${gc.clientId}")
    private String clientId;
    @Resource
    private ComponentEsServiceImpl componentEsServiceImpl;
    @Autowired
    private ComponentModelSbDao componentModelSbDao;
    @Resource
    private ComponentModel3dServiceImpl componentModel3dService;
    @Resource
    private ComponentModelFPServiceImpl componentModelFPService;
    @Resource
    private ComponentModelSbServiceImpl componentModelSbService;
    @Resource
    private headerServiceImpl headerService;
    @Resource
    private HeaderDao headerDao;

    @Resource
    private CategoryApi categoryApi;

    @Override
    public Map getComponent(String number) {

        List<Map<String, Object>> updatedMap = new ArrayList<>();
        try {
            LambdaQueryWrapper<ComponentData> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.like(ComponentData::getPartNumber, number);
            Page<ComponentData> page = new Page<>(1, 50);
            Page<ComponentData> componentDataPage = componentDao.selectPage(page, queryWrapper);

            List<ComponentData> componentDataList = componentDataPage.getRecords();
            List<ComponentDataHeaderField> fieldList;
            //本地没有 远程国创获取
            if (CollectionUtils.isEmpty(componentDataList)) {
                ModelApplication modelApplication = new ModelApplication();
                modelApplication.setPartNumber(number);
                modelApplication.setType(2);
                //调用接口
                List<ComponentInfo> infoByPartNumber = getInfoByPartNumber(modelApplication);
                if (CollectionUtils.isEmpty(infoByPartNumber)) {
                    return null;
                }
                for (ComponentInfo componentInfo : infoByPartNumber) {
                    fieldList = componentInfo.getComponentDataHeaderFieldList();
                    String jsonString = componentInfo.getComponentData().getTechTemplateFields();
                    // 转换为 Map
                    Map<String, String> fieldMapping = fieldList.stream()
                            .collect(Collectors.toMap(ComponentDataHeaderField::getFieldKey, ComponentDataHeaderField::getFieldName));

                    // 解析JSON字符串为Map
                    ObjectMapper objectMapper = new ObjectMapper();
                    Map<String, String> fieldsMap = objectMapper.readValue(jsonString, new TypeReference<Map<String, String>>() {
                    });
                    // 替换键名
                    Map<String, Object> hashMap = new HashMap<>();
                    for (Map.Entry<String, String> entry : fieldsMap.entrySet()) {
                        String newKey = fieldMapping.getOrDefault(entry.getKey(), entry.getKey());
                        hashMap.put(newKey, entry.getValue());
                    }
                    //获取目录信息
                    this.getCategoriesName( componentInfo.getComponentData().getSetId(),hashMap);
                    updatedMap.add(hashMap);
                }
                HashMap<Object, Object> newHashMap = MapUtil.newHashMap();
                newHashMap.put("total", infoByPartNumber.size());
                newHashMap.put("list", updatedMap);
                return newHashMap;
            }
            LambdaQueryWrapper<ComponentDataHeaderField> wrapper = Wrappers.lambdaQuery();
            List<Long> list = componentDataList.stream()
                    .map(ComponentData::getSetId)
                    .distinct()
                    .collect(Collectors.toList());
            wrapper.in(ComponentDataHeaderField::getSetId, list);
            fieldList = componentDataHeaderFieldDao.selectList(wrapper);
            //分组
            Map<Long, List<ComponentDataHeaderField>> longListMap = fieldList.stream()
                    .collect(Collectors.groupingBy(ComponentDataHeaderField::getSetId));
            for (ComponentData componentData : componentDataList) {
                List<ComponentDataHeaderField> headerFieldList = longListMap.get(componentData.getSetId());
                String jsonString = componentData.getTechTemplateFields();

                // 转换为 Map
                Map<String, String> fieldMapping = headerFieldList.stream()
                        .collect(Collectors.toMap(ComponentDataHeaderField::getFieldKey, ComponentDataHeaderField::getFieldName));
                // 解析JSON字符串为Map
                ObjectMapper objectMapper = new ObjectMapper();
                Map<String, String> fieldsMap = objectMapper.readValue(jsonString, new TypeReference<Map<String, String>>() {
                });
                // 替换键名
                Map<String, Object> hashMap = new HashMap<>();
                for (Map.Entry<String, String> entry : fieldsMap.entrySet()) {
                    String newKey = fieldMapping.getOrDefault(entry.getKey(), entry.getKey());
                    addData(hashMap,newKey,entry.getValue());
                }
                //获取目录信息
                this.getCategoriesName(componentData.getSetId(),hashMap);
                updatedMap.add(hashMap);
            }
            HashMap<Object, Object> newHashMap = MapUtil.newHashMap();
            newHashMap.put("total", updatedMap.size());
            newHashMap.put("list", updatedMap);
            return newHashMap;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    private static void addData(Map<String, Object> hashMap,String newKey,Object value) {
        // 如果 Map 中已经包含该键
        if (hashMap.containsKey(newKey)) {
            // 获取对应的值，并添加值
            String str = (String) hashMap.get(newKey);
            String s = str + value.toString();
            hashMap.put(newKey, s);
        } else {
            // 否则创建一个新的集合，添加值，并放入 Map
            hashMap.put(newKey,value);
        }
    }
    public static List<Map<String, Object>> getPaginatedList(List<Map<String, Object>> list, int pageSize, int pageNumber) {
        if (list == null || pageSize <= 0 || pageNumber <= 0) {
            throw new IllegalArgumentException("Invalid input parameters");
        }

        int totalSize = list.size();
        int startIndex = (pageNumber - 1) * pageSize;
        int endIndex = Math.min(startIndex + pageSize, totalSize);

        // 确保 startIndex 不超过总数据量
        if (startIndex >= totalSize) {
            return new ArrayList<>(); // 返回空列表
        }

        return list.subList(startIndex, endIndex);
    }

    @Override
    public String viewPreview(String number) {
        LambdaQueryWrapper<ComponentData> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(ComponentData::getPartNumber, number);
        ComponentData componentData = componentDao.selectOne(queryWrapper);
        if (Objects.nonNull(componentData)) {
            return componentData.getId().toString();
        }
        return null;
    }

    @Override
    public List<ComponentInfo> getInfoByPartNumber(ModelApplication modelApplication) throws MeException {
        try {
            // 定义请求参数
            String url = gcUrl + "/resource/openapi/v1/component/private/find";
            //定义参数
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("partNumber", modelApplication.getPartNumber());
            paramMap.put("orgName", modelApplication.getOrgName());
            paramMap.put("type", modelApplication.getType());
            List<Map<String, Object>> list = new ArrayList<>();
            list.add(paramMap);
            // 添加自定义头部参数
            String authorizationToken = GCutil.getToken();
            Map<String, String> headers = new HashMap<>();
            headers.put("client-id", clientId);
            headers.put("Authorization", authorizationToken);

            HttpResponse response = HttpRequest.post(url)
                    .body(JSONUtil.toJsonStr(list))  // 设置请求体
                    .addHeaders(headers)  // 设置请求头，表示发送的是JSON数据
                    .execute();  // 执行请求

            if (!Objects.equals(response.getStatus(), HttpStatus.HTTP_OK)) {
                throw new MeException("getInfoByPartNumber(),请求异常：" + response.body());
            }

            JSONObject jsonObject = JSONObject.parseObject(response.body());
            JSONArray dataArray = jsonObject.getJSONArray("data");
            if (Objects.isNull(dataArray)) {
                log.info("请求返回数据:{}", JSONUtil.toJsonStr(response.body()));
                XxlJobHelper.log(JSONUtil.toJsonStr(response.body()));
                return null;
            }
            List<ModelApplication> modelApplications = dataArray.toJavaList(ModelApplication.class);

            if (CollectionUtils.isEmpty(modelApplications)) {
                log.info("getInfoByPartNumber(),数据为空");
                XxlJobHelper.log("getInfoByPartNumber(),数据为空");
                return null;
            }
            ObjectMapper mapper = new ObjectMapper();
            List<ComponentInfo> componentInfoList = new ArrayList<>();
            for (ModelApplication application : modelApplications) {
                // 定义请求参数
                String idUrl = gcUrl + "/resource/openapi/v1/component/private/batchGet";
                //定义参数
                Map<String, Object> paramIdMap = new HashMap<>();
                paramIdMap.put("idList", application.getId());
                HttpResponse httpResponse = HttpRequest.get(idUrl)
                        .form(paramIdMap)
                        .addHeaders(headers)
                        .execute();

                if (!Objects.equals(httpResponse.getStatus(), HttpStatus.HTTP_OK)) {
                    throw new MeException("请求异常：" + httpResponse.body());
                }
                JSONObject parseObject = JSONObject.parseObject(httpResponse.body());
                JSONArray data = parseObject.getJSONArray("data");
                if (CollectionUtils.isEmpty(data)) {
//                    log.info("data数据为空");
                    XxlJobHelper.log("data数据为空");
                    return null;
                }

                for (int i = 0; i < data.size(); i++) {
                    ComponentInfo componentInfo = new ComponentInfo();
                    JSONObject json = data.getJSONObject(i);
                    ComponentData componentData = mapper.readValue(json.getString("component"), ComponentData.class);
//                Header header = mapper.readValue(json.getString("header"), Header.class);
                    JSONArray fieldsArray = json.getJSONArray("fields");
                    List<ComponentDataHeaderField> fieldList = JSONArray.parseArray(fieldsArray.toJSONString(), ComponentDataHeaderField.class);
                    componentInfo.setComponentData(componentData);
                    componentInfo.setComponentDataHeaderFieldList(fieldList);
                    componentInfoList.add(componentInfo);
                }
                callbackNotificationService.extracted(data);
            }
            return componentInfoList;
        } catch (MeException | JsonProcessingException e) {
            throw new MeException(e.getMessage());
        }
    }


    private void getCategoriesName(Long setId,Map<String, Object> hashMap) {

        Header header = headerDao.selectById(setId);
        Long platformCategoryId = header.getPlatformCategoryId();

        CategoryRespDTO firstCategory;
        CategoryRespDTO secondCategory;
        CategoryRespDTO thirdCategory = categoryApi.getById(platformCategoryId).getData();
        secondCategory = categoryApi.getById(thirdCategory.getParentId()).getData();
        String splitStr = "/";
        if (Objects.isNull(secondCategory) || Objects.isNull(secondCategory.getId())) {
            hashMap.put("categoriesName",thirdCategory.getName());
        } else {
            //获取一级分类
            firstCategory = categoryApi.getById(secondCategory.getParentId()).getData();
            StringBuilder stringBuilder = new StringBuilder();
            if (Objects.nonNull(firstCategory) && Objects.isNull(firstCategory.getId())) {
                stringBuilder.append(secondCategory.getName()).append(splitStr).append(thirdCategory.getName());
                hashMap.put("categoriesName",stringBuilder.toString());
            } else {
                stringBuilder.append(firstCategory.getName()).append(splitStr);
                stringBuilder.append(secondCategory.getName()).append(splitStr).append(thirdCategory.getName());
                hashMap.put("categoriesName",stringBuilder.toString());
            }
        }
    }

    /**
     * 返回1代表有值，2代表有值但是都存在了,3代表无值
     *
     * @param modelApplication
     * @return
     * @throws MeException
     */
    @Override
    public Integer partNumber2Id(ModelApplication modelApplication) throws MeException {
        // 定义请求参数
        String url = gcUrl + "/resource/openapi/v1/component/private/find";
        //定义参数
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("partNumber", modelApplication.getPartNumber());
        paramMap.put("orgName", modelApplication.getOrgName());
        paramMap.put("type", modelApplication.getType());
        List<Map<String, Object>> list = new ArrayList<>();
        list.add(paramMap);
        // 添加自定义头部参数
        String authorizationToken = GCutil.getToken();
        Map<String, String> headers = new HashMap<>();
        headers.put("client-id", clientId);
        headers.put("Authorization", authorizationToken);

        HttpResponse response = HttpRequest.post(url)
                .body(JSONUtil.toJsonStr(list))  // 设置请求体
                .addHeaders(headers)  // 设置请求头，表示发送的是JSON数据
                .execute();  // 执行请求

        if (!Objects.equals(response.getStatus(), HttpStatus.HTTP_OK)) {
            throw new MeException("getInfoByPartNumber(),请求异常：" + response.body());
        }

        JSONObject jsonObject = JSONObject.parseObject(response.body());
        JSONArray dataArray = jsonObject.getJSONArray("data");
        if (Objects.isNull(dataArray) || dataArray.isEmpty()) {
            log.info("artNumber2Id请求返回数据是空:{}", JSONUtil.toJsonStr(response.body()));
            XxlJobHelper.log(JSONUtil.toJsonStr(response.body()));
            return 3;
        }
        List<ModelApplication> modelApplications = dataArray.toJavaList(ModelApplication.class);
        Set<Long> idList = modelApplications.stream().map(ModelApplication::getId).collect(Collectors.toSet());

        List<CallbackNotification> callbackNotifications = callbackNotificationDao.selectList(Wrappers.<CallbackNotification>lambdaQuery()
                .in(CallbackNotification::getResourceId, idList));
        Set<Long> queryIdList = callbackNotifications.stream().map(CallbackNotification::getResourceId).collect(Collectors.toSet());
        if (queryIdList.size() == idList.size()) {
            log.info("partNumber2Id请求返回数据都存在:{}", JSONUtil.toJsonStr(response.body()));
            return 2;
        }
        modelApplications = modelApplications.stream().filter(x -> !queryIdList.contains(x.getId())).collect(Collectors.toList());

        for (ModelApplication application : modelApplications) {
            CallbackNotification callbackNotification = new CallbackNotification();
            callbackNotification.setSynStatus(0);
            callbackNotification.setModeType(2);
            callbackNotification.setCreateTime(LocalDateTime.now());
            callbackNotification.setPartNumber(modelApplication.getPartNumber());
            callbackNotification.setCreateBy(modelApplication.getCreateBy());
            callbackNotification.setResourceId(application.getId());
            callbackNotificationDao.insert(callbackNotification);
        }
        return 1;

    }

    @Override
    public void updateESData(List<String> ids) throws MeException {
        ComponentSyncDTO syncDTO = new ComponentSyncDTO();

        //数据组装
        List<ComponentData> componentDataList = this.listByIds(ids);
        List<String> model3dIdList = componentDataList.stream()
                .map(data -> data.getModel3dId() != null ? data.getModel3dId().toString() : null)
                .collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(componentDataList)){
            List<ComponentModel3d> componentModel3ds = componentModel3dService.listByIds(model3dIdList);

            List<String> fpList = componentDataList.stream()
                    .map(data -> data.getFootprintId() != null ? data.getModel3dId().toString() : null)
                    .collect(Collectors.toList());
            List<ComponentModelFP> componentModelFPS = componentModelFPService.listByIds(fpList);

            List<String> sbList = componentDataList.stream()
                    .map(data -> data.getSymbolId() != null ? data.getModel3dId().toString() : null)
                    .collect(Collectors.toList());
            List<ComponentModelSb> componentModelSbs = componentModelSbService.listByIds(sbList);

            List<Long> longList = componentDataList.stream().map(ComponentData::getSetId).distinct().collect(Collectors.toList());
            List<Header> headerList = headerService.listByIds(longList);

            //component_data_header_field
            List<ComponentDataHeaderField> fieldList = new ArrayList<>();

            for (Long setId : longList) {
                LambdaQueryWrapper<ComponentDataHeaderField> queryWrapper = Wrappers.lambdaQuery();
                queryWrapper.eq(ComponentDataHeaderField::getSetId,setId);
                List<ComponentDataHeaderField> fields = componentDataHeaderFieldDao.selectList(queryWrapper);
                fieldList.addAll(fields);
            }


            syncDTO.setComponentDataList(componentDataList);
            syncDTO.setComponentModel3dList(componentModel3ds);
            syncDTO.setComponentModelFpList(componentModelFPS);
            syncDTO.setComponentModelSbList(componentModelSbs);
            syncDTO.setComponentDataHeaderFieldList(fieldList);
            syncDTO.setComponentDataHeaderList(headerList);
            syncDTO.setTaskType(2);
            componentEsServiceImpl.saveComponentIndexData(syncDTO);
        }

    }
}
